#ifndef CONNECTION_H
#define CONNECTION_H

#pragma once
#include "Socket.h"
#include "Buffer.h"
#include "Channel.h"
#include <unistd.h>
#include <functional>
#include <memory>
#include <atomic>
#include <chrono>
class EventLoop;
class Connection;
using ConnectionSptr = std::shared_ptr<Connection>;
class Connection: public std::enable_shared_from_this<Connection>
{
public:
    Connection(EventLoop* loop, Socket* cs);
    Connection() = default;
    ~Connection();
    // 发送消息肯定会调用，如果是Io线程就直接发送，如果是工作线程需要提交到IO线程，负责发送
    // 统一交给IO线程发送，避免操作同一缓冲区，也不用使用锁
    void sendMsg(const std::string& msg);
    // 工作线程调用，提交到IO线程发送
    void submitSendMsg(const std::string& msg);
    
    void setMessageCb(std::function<void(ConnectionSptr, const std::string)> fun) {
        this->messageCb_ = fun;
    }
    void setExitCb(std::function<void(ConnectionSptr)> fun) {
        this->exitCb_ = fun;
    }
    void setErrorCb(std::function<void(ConnectionSptr)> fun) {
        this->errorCb_ = fun;
    }
    int getFd() {
        return clientSock_->GetFd();
    }
    std::ostream& showInfo() {
        return clientSock_->showInfo();
    }
    bool isClose() {
        return isClose_;
    }
    void close() {
        isClose_ = true;
    }
    bool isTimeout(int val) {
        return time(nullptr) - connTime_ >= val;
    }
    void closeConn() {
        close();
        onExit();
    }
private:
    std::atomic_bool isClose_ {false};
    EventLoop* loop_ = nullptr;
    Socket* clientSock_ = nullptr;
    Channel* clientCh_ = nullptr;
    // 记录连接时间
    time_t connTime_;
    Buffer outBuff_;
    Buffer inBuff_;
    // 读回调
    void onMessage();
    void onWrite();
    void onExit();
    void onError();

    // 将数据解包后进行业务处理
    std::function<void(ConnectionSptr, const std::string)> messageCb_;
    std::function<void(ConnectionSptr)> errorCb_;
    std::function<void(ConnectionSptr)> exitCb_;

    void parseMsg();
};

#endif